/*
 * @Author       : Zhao Lvhua zhaolh@linkcharging.com
 * @Date         : 2024-09-02 01:04:00
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 13:02:00
 * @FilePath     : \openchaoji-corelib\shared\src\OpenChaoJi_utility_transport_gbt27930_a_send.c
 * @Description  :
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "OpenChaoJi_utility_transport_gbt27930_a.h"
#include "OpenChaoJi_utility_transport_gbt27930_a_private.h"

extern bool s_transport_debug_enable;

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_A == CONFIG_YES)

int16_t OpenChaoJi_transport_gbt27930_a_ursm_send(struct OpenChaoJi_gbt27930_a_urmcb * urmcb, const struct can_data * send_data)
{
	int16_t ret;
    struct can_pdu pdu;

	pdu.can_id = send_data->can_id;
	pdu.can_dlc = send_data->len;
	memcpy(pdu.data,send_data->data,send_data->len);

    // 例如短包直接发送
    ret = (*urmcb->can_output_func)(urmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->a_rsm[%08X][%d]", urmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}


int16_t OpenChaoJi_transport_gbt27930_a_rm_write(struct OpenChaoJi_gbt27930_a_rmcb * rmcb, const struct can_data * send_data)
{
	struct OpenChaoJi_gbt27930_a_rmcb *Mscb = rmcb;

	if (send_data->len <= 8)
	{
		//短消息发送处理

	}
	else
	{
		//长消息处理
		if (Mscb->lm_send_state != LM_SEND_IDLE)
		{
            //目前处于发送中，无法再次发送新的消息，go to error
			// LOG_ERR("transportsend long message, current is't idle, dont't send new message");
			return -1;
		}

		OPEN_CHAOJI_MEM_FREE_CHECK(Mscb->lm_send_buf);
		Mscb->lm_send_buf = OpenChaoJi_os_malloc(send_data->len);
		if (Mscb->lm_send_buf == NULL)
		{
			//内存申请失败 go to error
			LOG_ERR("transportsend malloc null");
			return -1;
		}

		Mscb->lm_send_pgn = ((uint32_t)(send_data->can_id.bit.pf))<<8;

		// int send_i = 0;
		//保存数据副本
//        printf("transport:Mscb->lm_send_buf = [%d] \r\n", Mscb->lm_send_buf);
//		printf("transport:send_data->len = [%d] [\r\n", send_data->len);
        // TODO 添加打印
//		for(send_i = 0; send_i <send_data->len; send_i++)
//		{
//		    printf("%02X ", send_data->data[send_i]);
//		}
//		printf("]\r\n");
		//memcpy(Mscb->lm_send_buf,send_data->data,send_data->len);

        for (int i = 0; i < send_data->len; i++){
            Mscb->lm_send_buf[i] = send_data->data[i];
        }

		Mscb->lm_send_tbytes = send_data->len;
		Mscb->lm_send_tfra = send_data->len/7+(((send_data->len%7)==0)?0:1);
		Mscb->lm_send_cnt = 0;
		Mscb->lm_resend_cnt = 0;

		//发送LM(0),开启 LMS_T2,LMS_T3,进入S0
		gbt27930_a_rlm_do_connect(rmcb);
		Mscb->lm_send_lms_t1_tick = 0;
		Mscb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
		Mscb->lm_send_lms_t3_tick = OpenChaoJi_os_get_ticks();
		Mscb->lm_send_state = LM_SEND_S0_ESTB_CONN;
		Mscb->rcved_ack_flag = TPCM_INVALID_VALUE;
	}

	return 0;
}

int16_t OpenChaoJi_transport_gbt27930_a_rlm_send_process(struct can_pdu * pdu, struct OpenChaoJi_gbt27930_a_rmcb * rmcb)
{

	int16_t error = 0;

	switch (rmcb->lm_send_state)
	{
		case LM_SEND_IDLE:

			break;

		case LM_SEND_S0_ESTB_CONN:
			LOG_DEBUG("rmcb->rcved_ack_flag = [%X]", rmcb->rcved_ack_flag);
			if (rmcb->rcved_ack_flag == TPCM_CTS)
			{
				//根据应答发送 LM(n), send_cnt 置 1. 开启LMS T1,关闭 LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[2];
				rmcb->lm_ack_totalframe_nums = pdu->data[1];

				error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == TPCM_ABORT)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				if (rmcb->lm_resend_cnt >= 3)
				{
					gbt27930_a_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
                    LOG_INFO("transportsend resend cnt > 3 close connect");
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S0
					gbt27930_a_rlm_do_connect(rmcb);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_a_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
                LOG_INFO("transportsend T3 timeout, close connect");
			}

			break;

		case LM_SEND_S1_DATA_TRAN:	//data transmission

			if (rmcb->rcved_ack_flag == TPCM_CTS)
			{
				//保存k,根据应答发送LM(n), send_cnt置1,开启LMS_T1,关LMS_T2,保持S1
				rmcb->lm_ack_startframe_idx = pdu->data[2];
				rmcb->lm_ack_totalframe_nums = pdu->data[1];
				error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
                LOG_INFO("transportsend rmcb->lm_ack_startframe_idx = %d rmcb->lm_ack_totalframe_nums = %d",
							rmcb->lm_ack_startframe_idx, rmcb->lm_ack_totalframe_nums);
			}
			else if (rmcb->rcved_ack_flag == TPCM_ABORT)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
                LOG_DEBUG("transportrecv traning ev close connect");
			}

			//信息帧发送时间间隔LMS_T1定时器到
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t1_tick) >= rmcb->lm_send_lms_t1_intvl_ms)
			{
				//期望发送为长消息最后一帧
				if ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) == rmcb->lm_send_tfra)
				{
					//发送LM(lm_tfra),send_cnt加1，关闭LMS_T1,开启LMS_T2,进入S3等待结束确认状态
					error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_send_tfra);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S3_AWAIT_FIN_ACK;
					rmcb->lm_resend_cnt = 0;
					//LOG_DEBUG(" LMS_T1 1");
                    LOG_DEBUG("transportrecv long frame is the last one");

				}
				//期望发送帧非接收方请求的最后一帧，且非长消息最后一帧
				else if ((rmcb->lm_send_cnt < (rmcb->lm_ack_totalframe_nums - 1))
						&& ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) < rmcb->lm_ack_totalframe_nums))
				{
					//发 送 L M ( n + send_cnt),send cnt加1,重置 LMS_ T1,保持Sl
					error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
					LOG_DEBUG(" LMS_T1 2");
				}

				//期望发送帧为接收方请求的最后一帧且非长消息最后一帧，send_cnt = k- 1且n+send_cnt<lm tfra
				else if ((rmcb->lm_send_cnt == (rmcb->lm_ack_totalframe_nums - 1))
						&& ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) < rmcb->lm_ack_totalframe_nums))
				{
					//发 送 L M ( n + send_cnt),send cnt加1 . 关闭 LMS T1,开启LMS_ T2,进入S2
					error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S2_AWAIT_RESP_ACK;
					rmcb->lm_resend_cnt = 0;
					//LOG_DEBUG(" LMS_T1 3");
                    LOG_DEBUG("transportrecv long package is the last one");
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_a_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
                LOG_DEBUG("transportrecv T3 timeout close connect");
			}

			break;

		case LM_SEND_S2_AWAIT_RESP_ACK:
            LOG_DEBUG("LM_SEND_S2_AWAIT_RESP_ACK::rmcb->rcved_ack_flag =  %d",rmcb->rcved_ack_flag);
			if (rmcb->rcved_ack_flag == TPCM_CTS)
			{
				//根据应答调整LM的帧序号为n, send_cnt 置 1, 开启LMS_T1,关闭LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[2];
				rmcb->lm_ack_totalframe_nums = pdu->data[1];

				error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == TPCM_ABORT)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}
			//如果接收方连  续3次超时，发送LM_NACK,进入S4,否则发送LM(n+k—1),开启LMST2,进入S2
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				if (rmcb->lm_resend_cnt >= 3)
				{
					gbt27930_a_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
                    LOG_DEBUG("transportrecv LM_SEND_S2_AWAIT_RESP_ACK timeout");
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S0
					error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx + rmcb->lm_ack_totalframe_nums -1);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_a_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
			}

			break;

		case LM_SEND_S3_AWAIT_FIN_ACK:
            LOG_DEBUG("LM_SEND_S3_AWAIT_FIN_ACK::rmcb->rcved_ack_flag = %d", rmcb->rcved_ack_flag);
			if (rmcb->rcved_ack_flag == TPCM_CTS)
			{
				//根据应答调整LM的帧序号为n, send_cnt 置 1, 开启LMS_T1,关闭LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[2];
				rmcb->lm_ack_totalframe_nums = pdu->data[1];

				error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == TPCM_ABORT)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}
			else if (rmcb->rcved_ack_flag == TPCM_EndACK)
			{
				//LM_EndofACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}

			//如果接收方连续3次响应超时，发送LMN_ACK,进入S4,否则发送LM(lm_tfra),开启LMS_T2,保持S3
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				if (rmcb->lm_resend_cnt >= 3)
				{
					gbt27930_a_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
                    LOG_DEBUG("transportrecv LM_SEND_S3_AWAIT_FIN_ACK timeout");
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S3
					error = gbt27930_a_rlm_sent_data(rmcb,rmcb->lm_send_tfra);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_a_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
			}
			break;

		case LM_SEND_S4_CLOSE_CONN:
				rmcb->lm_send_lms_t1_tick = 0;
				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_lms_t3_tick = 0;
				rmcb->lm_send_cnt = 0;
				rmcb->lm_resend_cnt = 0;
				// OpenChaoJi_os_free(rmcb->lm_send_buf);
				OPEN_CHAOJI_MEM_FREE_CHECK(rmcb->lm_send_buf);
				rmcb->lm_send_state = LM_SEND_IDLE;
			break;

		default: break;
	}

   	if (error < 0)
	{
		LOG_CRIT("system b rlm send error");
	}

	return 0;
}

//长消息发送连接
int16_t gbt27930_a_rlm_do_connect(struct OpenChaoJi_gbt27930_a_rmcb * rmcb)
{

	struct can_pdu pdu;
    int16_t ret;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;

	pdu.can_id.bit.pf = (PGN_TPCM>>8);
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 7;
	pdu.can_id.bit.rsvd = 0;
	pdu.can_dlc = 8;

	pdu.data[0] = TPCM_RTS;
	pdu.data[1] = rmcb->lm_send_tbytes & 0x00ff;//总字节数
	pdu.data[2] = rmcb->lm_send_tbytes>>8;
	pdu.data[3] = rmcb->lm_send_tfra;			//发送总帧数
	pdu.data[4] = 0xff;
	pdu.data[5] = ((rmcb->lm_send_pgn)&0xff);
	pdu.data[6] = ((rmcb->lm_send_pgn >> 8)&0xff);
	pdu.data[7] = ((rmcb->lm_send_pgn >> 16)&0xff);

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->a_rlm_conn[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}


int16_t gbt27930_a_rlm_sent_data(struct OpenChaoJi_gbt27930_a_rmcb * rmcb,uint8_t frame_idx)
{
	struct can_pdu pdu;
	uint8_t i;
    int16_t ret;
	uint16_t offset = (frame_idx-1)*7;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;
	pdu.can_id.bit.pf = (PGN_TPDT>>8);
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 0x07;
	pdu.can_id.bit.rsvd = 0;

	pdu.can_dlc = 8;

	pdu.data[0] = frame_idx;
	//不足7字节的填充OxFF
	for (i = 0;i < 7;i++)
	{
		if ((offset+i) < rmcb->lm_send_tbytes){
			pdu.data[i+1] = rmcb->lm_send_buf[offset+i];
		}
		else{
			pdu.data[i+1] = 0xff;
		}
	}

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->a_rlm_data[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}
#endif
